#include "HashPoint.h"
#include <stdio.h>

HashPoint::HashPoint(){}
HashPoint::~HashPoint(){}
HashPoint::HashPoint(double Time, long Hash)
	{
		this->Time = Time;
		this->Hash = Hash;
	}

	//Compute Hash of 4 frequency points
long HashPoint::CalculateHash(long f1, long f2, long f3, long f4)
	{
		return (f4 - (f4 % FUZ_FACTOR)) * 100000000 + (f3 - (f3 % FUZ_FACTOR)) * 100000 + (f2 - (f2 % FUZ_FACTOR)) * 100 + (f1 - (f1 % FUZ_FACTOR));
	}

	//Compute Hash of 3 frequency points
long HashPoint::CalculateHash(long f1, long f2, long f3)
	{
		return (f3 - (f3 % FUZ_FACTOR)) * 100000 + (f2 - (f2 % FUZ_FACTOR)) * 100 + (f1 - (f1 % FUZ_FACTOR));
	}

	//Get Group Hash 3 Points of Highest Magnitude of Spectrogram
HashPoint* HashPoint::getGrHash3Point(Dictionary HighPointsSpec, int *size)
	{
		
		int rows = HighPointsSpec.get_frequency_rows();
		int cols = HighPointsSpec.get_spectrum_columns();
		
		//highpoints [757][147]
		//hash 3Points: 147/3 = 49
		//lengthg = 49*757 = 37093 
		*size = (rows * (cols/3));
		HashPoint* dataPointsHash = new HashPoint[*size]; //List to be returned

		//times
		int hNumber = 0;
		for (int t = 0 ; t < rows; t++)
		{
			//freq
			for (int f = 0; f < cols; f = f + 3)
			{
				//key is times
				if (f + 3 <= cols)
					dataPointsHash[hNumber++] = HashPoint(HighPointsSpec.Time[t], 
					CalculateHash((long)HighPointsSpec.Frequency[t][f],
						(long)HighPointsSpec.Frequency[t][f+1], (long)HighPointsSpec.Frequency[t][f+2]));
			}
		}

		return dataPointsHash;
	}

	//Get Group Hash 4 Points of Highest Magnitude of Spectrogram
HashPoint* HashPoint::getGrHash4Point(Dictionary HighPointsSpec, int *size)
	{
		int rows = HighPointsSpec.get_frequency_rows();
		int cols = HighPointsSpec.get_spectrum_columns();

		*size = (int) (HighPointsSpec.get_frequency_rows() * (HighPointsSpec.get_spectrum_columns()/4));
		HashPoint* dataPointsHash = new HashPoint[*size]; //List to be returned
		//highpoints [757][147]
		//hash 3Points: 147/3 = 49
		//lengthg = 49*757 = 37093


		//times
		int hNumber = 0;
		for (int t = 0 ; t < rows; t++)
		{
			//freq
			for (int f = 0; f < cols; f = f + 4)
			{
				//key is times
				if (f + 4 <= cols)
					dataPointsHash[hNumber++] = HashPoint(HighPointsSpec.Time[t], 
					CalculateHash((long)HighPointsSpec.Frequency[f],
					(long)HighPointsSpec.Frequency[f+1], (long)HighPointsSpec.Frequency[f+2],
					(long)HighPointsSpec.Frequency[f+3]));
			}
		}

		return dataPointsHash;
}

//Get List Match of Hash Points
std::vector<Match> HashPoint::getMatchHashPoint(HashPoint* dataHashPointsOriginal, int sizeofOrigin,  HashPoint* dataHashPointsRecording, int sizeofRecording)
{
	//List Match of Hash Points
	std::vector<Match> listMatches;

	//Recording
	for (int i = 0; i < sizeofRecording; i++)
	{
		for (int j = 0; j < sizeofOrigin; j++)
		{
			if (dataHashPointsRecording[i].Hash == dataHashPointsOriginal[j].Hash)
			{
				listMatches.push_back( Match( (dataHashPointsOriginal[j].Time - dataHashPointsRecording[i].Time),
					dataHashPointsOriginal[j].Time,
					dataHashPointsRecording[i].Time ) );

			}
		}
	}
	
	return listMatches;
}

std::vector<double> HashPoint::getMatchingNumbers(std::vector<Match> matchArray, double *matchingNumber)
{
	//Values	
	std::vector<double> distinctNumbers;
	*matchingNumber = 0;
	bool seenThisIntBefore = false;

	for(int j = 0; j < (int)matchArray.size(); j++)
	{
		//Check if we've seen it before (by checking all array indexes below j)
		seenThisIntBefore = false;
		for (int i = 0; i < j; i++)
			if (matchArray[j].Offset == matchArray[i].Offset)
			{
				seenThisIntBefore = true;
			}

		//If we have not seen the integer before, increment the running total of distinct integers
		if (!seenThisIntBefore)
			distinctNumbers.push_back(matchArray[j].Offset);
		else
			(*matchingNumber)++;
	}

	return distinctNumbers;
}

//double HashPoint::countTheNumberOfMatchingPoints(std::vector<Match> matchArray)
//{
//	std::vector<double> distinctNumbers;
//	distinctNumbers = getDistinctNumbers(matchArray);
//
//
//}